package com.zkn.orm.jboss.jpa.dao.impl;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import com.zkn.orm.jboss.jpa.dao.DepartmentDao;
import com.zkn.orm.spring.data.jpa.model.Department;

/**
 * Hibernate EntityManager实例：
 * 
 * 使用Hibernate EntityManager 和使用Hibernate Core 是差不多的,只不过 EntityManger还可以方便的在JEE容器中使用,这就是EJB3 的持久化实现机制.
 * 
 * 实体对象拥有以下4个状态，这些状态通过调用EntityManager接口方法发生迁移：
 * 1. 新建态：新创建的实体对象，尚未拥有持久化主键，没有和持久化上下文关联起来。
 * 2. 受控态：已经拥有持久化主键并和持久化上下文建立了联系；
 * 3. 游离态：拥有持久化主键，但尚未和持久化上下文建立联系；
 * 4. 删除态：拥有持久化主键，已经和持久化上下文建立联系，但已经被安排从数据库中删除。
 * 
 * @author Administrator
 *
 */
/*
	实体对象由实体管理器进行管理，JPA使用javax.persistence.EntityManager代表实体管理器。
	实体管理器和持久化上下文关联，持久化上下文是一系列实体的管理环境，我们通过EntityManager和持久化上下文进行交互。
	
	有两种类型的实体管理器：
	容器型（JavaEE容器，中间件服务器，JBoss等）：容器型的实体管理器由容器负责实体管理器之间的协作，
	在一个JTA事务中，一个实体管理器的持久化上下文的状态会自动广播到所有使用EntityManager的应用程序组件中。
	Java EE应用服务器提供的就是管理型的实体管理器；这个在后期讲解EJB时候再讲解使用。
	应用程序型：实体管理器的生命周期由应用程序控制，通过EntityManagerFactory的createEntityManager创建EntityManager实例。
	现在我们使用使用的就是应用程序型。
	
	下面是EntityManager的一些主要的接口方法：
	
	void persist(Object entity)
	新实体实例将转换为受控状态。这意谓着当persist ()方法所在的事务提交时，实体的数据将保存到数据库中。
	如果实体已经被持久化，那么调用persist()操作不会发生任何事情。如果对一个已经删除的实体调用persist()操作，
	删除态的实体又转变为受控态。如果对游离状的实体执行persist()操作，将抛出 IllegalArgumentException。
	在一个实体上调用persist()操作，将广播到和实体关联的实体上，执行相应的级联持久化操作；
	
	void remove(Object entity)
	通过调用remove()方法删除一个受控的实体。如果实体声明为级联删除(cascade=REMOVE 或者cascade=ALL )，
	被关联的实体也会被删除。在一个新建状态的实体上调用remove()操作，将被忽略。如果在游离实体上调用remove()操作，
	将抛出 IllegalArgumentException，相关的事务将回滚。如果在已经删除的实体上执行remove()操作，也会被忽略；
	
	void flush()
	将受控态的实体数据同步到数据库中；
	
	T merge(T entity)
	将一个游离态的实体持久化到数据库中，并转换为受控态的实体；
	
	T find(Class entityClass, Object primaryKey)
	以主键查询实体对象，这里使用的是即时加载。entityClass是实体的类，primaryKey是主键值，如以下的代码查询Student实体：
	
	Student t = em.find(Student.class,1);
	Query createQuery(String qlString)
	
	创建查询接口对象
 */
public class DepartmentDaoImpl implements DepartmentDao {

	private static final String persistenceUnitName = "SimplePU";
	
	/**
	 * 创建JPA事物步骤：
	 * 1. 创建EntityManagerFactory
	 * 2. 创建EntityManager
	 * 3. 开启一个事物
	 * 4. 持久化操作merge/persist/remove/find
	 * 5. 提交事物
	 * 6. 关闭EntityManager
	 */
	public Department save(Department department) {
		
		// 类似于Hibernate SessionFactory
		EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName); 
		// 类似于Hibernate Session
		EntityManager em = emf.createEntityManager(); 
		// 类似于Hibernate Transaction
		EntityTransaction et = em.getTransaction(); 
		
		et.begin();  //开启事物
		em.persist(department);
		et.commit(); //提交事物
		
		//释放资源
		em.close();
		emf.close();
		
		return department;
	}
}
